﻿using System;
using Awesomium.Core;
using System.Drawing;
using System.Windows.Forms;
using Awesomium.Windows.Forms;
using System.Runtime.InteropServices;

namespace WinFormsSample
{
    public partial class WebForm : Form
    {
        #region Fields
        WebView webView;
        RenderBuffer rBuffer;
        Bitmap frameBuffer;
        bool needsResize, repaint;
        #endregion


        #region Ctors
        public WebForm()
        {
            // Notice that Control.DoubleBuffered has been set to true
            // in the designer, to prevent flickering.

            InitializeComponent();

            webView = WebCore.CreateWebView( this.ClientSize.Width, this.ClientSize.Height );
            webView.ResizeComplete += OnResizeComplete;
            webView.IsDirtyChanged += OnIsDirtyChanged;
            webView.SelectLocalFiles += OnSelectLocalFiles;
            webView.CursorChanged += OnCursorChanged;
            webView.OpenExternalLink += OnOpenLink;
            //webView.DomReady += OnDOMReady;
            //webView.KeyboardFocusChanged += OnKeyboardFocus;
            webView.LoadURL( "http://www.google.com" );
            webView.Focus();
        }
        #endregion


        #region Methods
        private void ResizeView()
        {
            if ( ( webView == null ) || !webView.IsEnabled )
                return;

            if ( needsResize && !webView.IsResizing )
            {
                // Queue an asynchronous resize.
                webView.Resize( this.ClientSize.Width, this.ClientSize.Height );
                needsResize = false;
            }
        }

        protected override void OnActivated( EventArgs e )
        {
            base.OnActivated( e );

            if ( !webView.IsEnabled )
                return;

            webView.Focus();
        }

        protected override void OnDeactivate( EventArgs e )
        {
            base.OnDeactivate( e );

            if ( !webView.IsEnabled )
                return;

            webView.Unfocus();
        }

        protected override void OnFormClosed( FormClosedEventArgs e )
        {
            if ( webView != null )
            {
                webView.IsDirtyChanged -= OnIsDirtyChanged;
                webView.SelectLocalFiles -= OnSelectLocalFiles;
                webView.Close();
                WebCore.Shutdown();
            }

            base.OnFormClosed( e );
        }

        protected override void OnPaint( PaintEventArgs e )
        {
            if ( ( webView != null ) && webView.IsEnabled && webView.IsDirty )
                rBuffer = webView.Render();

            if ( rBuffer != null )
                Utilities.DrawBuffer( rBuffer, e.Graphics, this.BackColor, ref frameBuffer );
            else
                base.OnPaint( e );
        }

        protected override void OnResize( EventArgs e )
        {
            base.OnResize( e );

            if ( ( webView == null ) || !webView.IsEnabled )
                return;

            if ( this.ClientSize.Width > 0 && this.ClientSize.Height > 0 )
                needsResize = true;

            // Request resize, if needed.
            this.ResizeView();
        }

        protected override void OnKeyPress( KeyPressEventArgs e )
        {
            base.OnKeyPress( e );

            if ( !webView.IsEnabled )
                return;

            webView.InjectKeyboardEvent( e.GetKeyboardEvent() );
        }

        protected override void OnKeyDown( KeyEventArgs e )
        {
            base.OnKeyDown( e );

            if ( !webView.IsEnabled )
                return;

            webView.InjectKeyboardEvent( e.GetKeyboardEvent( WebKeyType.KeyDown ) );
        }

        protected override void OnKeyUp( KeyEventArgs e )
        {
            base.OnKeyUp( e );

            if ( !webView.IsEnabled )
                return;

            webView.InjectKeyboardEvent( e.GetKeyboardEvent( WebKeyType.KeyUp ) );
        }

        protected override void OnMouseDown( MouseEventArgs e )
        {
            base.OnMouseDown( e );

            if ( !webView.IsEnabled )
                return;

            webView.InjectMouseDown( MouseButton.Left );
        }

        protected override void OnMouseUp( MouseEventArgs e )
        {
            base.OnMouseUp( e );

            if ( !webView.IsEnabled )
                return;

            webView.InjectMouseUp( MouseButton.Left );
        }

        protected override void OnMouseMove( MouseEventArgs e )
        {
            base.OnMouseMove( e );

            if ( !webView.IsEnabled )
                return;

            webView.InjectMouseMove( e.X, e.Y );
        }

        protected override void OnMouseWheel( MouseEventArgs e )
        {
            base.OnMouseWheel( e );

            if ( !webView.IsEnabled )
                return;

            webView.InjectMouseWheel( e.Delta );
        }
        #endregion

        #region Event Handlers
        private void OnResizeComplete( object sender, ResizeEventArgs e )
        {
            if ( !webView.IsEnabled )
                return;

            if ( needsResize )
                this.ResizeView(); // Process pending resizing.

            // An IsDirtyChanged will normally be called
            // after resizing. Ask for a full invalidation.
            repaint = true;
        }

        private void OnIsDirtyChanged( object sender, EventArgs e )
        {
            if ( !webView.IsEnabled )
                return;

            if ( webView.IsDirty )
            {
                // Force repaint.
                if ( repaint )
                {
                    // Invalidate the whole surface.
                    this.Invalidate();
                    repaint = false;
                }
                else
                {
                    // Invalidate the dirty region only.
                    // This significantly improves performance.
                    this.Invalidate( webView.DirtyBounds.GetRectangle(), false );
                }
            }
        }

        private void OnCursorChanged( object sender, ChangeCursorEventArgs e )
        {
            Cursor = Utilities.GetCursor( e.CursorType );
        }

        private void OnSelectLocalFiles( object sender, SelectLocalFilesEventArgs e )
        {
            using ( OpenFileDialog dialog = new OpenFileDialog()
            {
                Title = e.Title,
                InitialDirectory = Environment.GetFolderPath( Environment.SpecialFolder.MyDocuments ),
                CheckFileExists = true,
                Multiselect = e.SelectMultipleFiles
            } )
            {
                if ( ( dialog.ShowDialog( this ) == DialogResult.OK ) || dialog.FileNames.Length > 0 )
                    e.SelectedFiles = dialog.FileNames;
                else
                    e.Cancel = true;
            }
        }

        private void OnOpenLink( object sender, OpenExternalLinkEventArgs e )
        {
            if ( !webView.IsEnabled )
                return;

            // For this sample, we load external links
            // in the same view.
            webView.LoadURL( e.Url );
        }

        //private void OnDOMReady( object sender, EventArgs e )
        //{
        //    webView.ExecuteJavascript( "document.getElementsByName('t')[0].focus();" );
        //}

        //private void OnKeyboardFocus( object sender, ChangeKeyboardFocusEventArgs e )
        //{
        //    if ( !webView.HasKeyboardFocus )
        //        return;

        //    WebKeyboardEvent keyEvent = new WebKeyboardEvent();
        //    var key = 'a';

        //    keyEvent.Type = WebKeyType.KeyDown;
        //    keyEvent.VirtualKeyCode = (VirtualKey)key;
        //    webView.InjectKeyboardEvent( keyEvent );

        //    keyEvent.Type = WebKeyType.Char;
        //    keyEvent.Text = new ushort[] { key, 0, 0, 0 };
        //    webView.InjectKeyboardEvent( keyEvent );

        //    keyEvent.Type = WebKeyType.KeyUp;
        //    keyEvent.VirtualKeyCode = (VirtualKey)key;
        //    webView.InjectKeyboardEvent( keyEvent );
        //}
        #endregion
    }

    #region NativeMethods
    internal static class NativeMethods
    {

        [DllImport( "user32" )]
        internal static extern IntPtr GetDC( IntPtr hwnd );

        [DllImport( "user32.dll" )]
        internal static extern bool ReleaseDC( IntPtr hWnd, IntPtr hDC );

    }
    #endregion
}